%{
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int Max_top = 100;
int Max_length_of_string = 100;
int min_top = 0;
struct _type_stack{
    int top;
    char type[100][100];
};
typedef struct _type_stack _type_stack;
void init_type_stack(_type_stack *stack){
    int i;
    stack->top = min_top-1;
    for(i = 0; i < Max_top; i++)
        memset(stack->type[i], 0, sizeof(char) * 100);
}
int push_to_stack(_type_stack *stack, char *InItem){
    stack->top++;
    if(stack->top > Max_top-1)
        return 1;
    sprintf(stack->type[stack->top], "%s", InItem);
    return 0;
}
int pop_from_stack(_type_stack *stack, char *OutItem){
    if(stack->top < min_top)
        return 1;
    sprintf(OutItem, "%s", stack->type[stack->top--]);
    return 0;
}
_type_stack Type_S;


%}

%token IDENTIFIER MAIN DOC LABEL PIC OBJ FOR SETSIZE SETFONT SETFONTSIZE PATH DIST POSITION
%token DIRECTION ANGLE DISTANCE TO INNER LEFT MIDDLE RIGHT TOP DOWN FROM CONTENT STRING 
%token RETURN DEFAULT FONT SIZE TYPEC CONTAINER POLY LETOUT ZAXIS AT AND OR WITH NUMBER
%token UNDERLINE EQUAL ASSIGN NOTEQ DOT GE GT LBRAC LE LT LPAREN MINUS PLUS RBRAC RPAREN
%token SEMICOLON SLASH STAR MOD LCURL RCURL COMMA IF CONSTANT ELSE

%left OR
%left AND



%%
code:
     declaration
  |  code declaration
  ;

declaration:
     function_definition
  |  variable_declaration
  ; 
variable_declaration:
     type_specifier init_declarator_list SEMICOLON
    ;

variable_declaration_list:
     variable_declaration
  |  variable_declaration_list COMMA variable_declaration
  ;


function_definition:
     MAIN LPAREN RPAREN compound_statement { printf("\npublic static void main(String[] arg){\n");
					      printf("%s\n", C_State);
					      printf("}\n");
					    }
  |  type_specifier IDENTIFIER LPAREN variable_declaration_list RPAREN  compound_statement{
						    
							printf("\n private static %s %s( %s ) {\n", Type_S, $2, V_D_L);
							printf("%s\n", C_State);
							printf("}\n");
						}
  |  type_specifier IDENTIFIER LPAREN compound_statement RPAREN{ 
							printf("\n private static %s %s( ) {\n", Type_S, $2);
							printf("%s\n", C_State);
							printf("}\n");}
  |  IDENTIFIER LPAREN variable_declaration_list RPAREN compound_statement{

							printf("\n private static void %s( %s ) {\n", Type_S, $2, V_D_L);
							printf("%s\n", C_State);
							printf("}\n");}
  |  IDENTIFIER LPAREN compound_statement RPAREN{
  
							printf("\n private static void %s( ) {\n", Type_S, $2);
							printf("%s\n", C_State);
							printf("}\n");}
;

type_specifier:
     NUMBER {sprintf(Type_S, "int");}
  |  STRING {sprintf(Type_S, "string");}
  |  DOC    {sprintf(Type_S, "MDoc");}
  |  OBJ    {sprintf(Type_S, "obj");}
  |  LABEL  {sprintf(Type_S, "Mlabel");}
  |  PIC    {sprintf(Type_S, "Mpic");}
  |  CONTAINER {sprintf(Type_S, "Mcontainer");}
  ;
init_declarator_list:
     init_declarator
  |  init_declarator_list COMMA init_declarator
  ;
init_declarator:
     IDENTIFIER
     array_declartor
  ;
array_declartor:
    IDENTIFIER LBRAC unary_expr LBRAC  
    ;

expression:
     assignment_expr
  |  expression COMMA assignment_expr
    ;

assignment_expr:
	logical_OR_expr
    |	unary_expr assignment_operator assignment_expr
    ;
assignment_operator:
     ASSIGN
  ;

logical_OR_expr:
     logical_AND_expr
  |  logical_OR_expr OR logical_AND_expr
  ;

logical_AND_expr:
     equality_expr
  |  logical_AND_expr AND equality_expr
  ;

equality_expr:
     relational_expr
  |  equality_expr EQUAL relational_expr
  |  equality_expr NOTEQ relational_expr
  ;

relational_expr:
     additive_expr
  |  relational_expr LT  additive_expr
  |  relational_expr GT  additive_expr
  |  relational_expr GE  additive_expr
  |  relational_expr LE  additive_expr
  ;


additive_expr:
     multiplicative_expr
  |  additive_expr PLUS multiplicative_expr
  |  additive_expr MINUS multiplicative_expr
  ;

multiplicative_expr:
     cast_expr
  |  multiplicative_expr STAR cast_expr
  |  multiplicative_expr SLASH cast_expr
  |  multiplicative_expr MOD cast_expr
  ;

cast_expr:
     unary_expr
  |  LPAREN type_specifier RPAREN cast_expr
  ;

unary_expr:
     IDENTIFIER
  |  IDENTIFIER DOT  IDENTIFIER
  |  CONSTANT
  |  IDENTIFIER LBRAC unary_expr RBRAC
;

statement:
     compound_statement
  |  expression_statement
  |  selection_statement
  |  iteration_statement
  ;
expression_statement:
     expression SEMICOLON
  |   SEMICOLON
  ;
selection_statement:
     IF LPAREN expression RPAREN statement
  |  IF LPAREN expression RPAREN statement ELSE statement
  ;
iteration_statement:
  |  FOR LPAREN expression SEMICOLON expression SEMICOLON expression RPAREN statement
  |  FOR LPAREN expression SEMICOLON expression SEMICOLON RPAREN statement
  |  FOR LPAREN expression SEMICOLON SEMICOLON expression RPAREN statement
  |  FOR LPAREN expression SEMICOLON SEMICOLON RPAREN statement
  |  FOR LPAREN SEMICOLON expression SEMICOLON expression RPAREN statement
  |  FOR LPAREN SEMICOLON expression SEMICOLON RPAREN statement
  |  FOR LPAREN SEMICOLON SEMICOLON expression RPAREN statement
  |  FOR LPAREN SEMICOLON SEMICOLON RPAREN statement
  |  FOR LPAREN declaration SEMICOLON expression SEMICOLON expression RPAREN statement
  |  FOR LPAREN declaration SEMICOLON expression SEMICOLON RPAREN statement
  |  FOR LPAREN declaration SEMICOLON SEMICOLON expression RPAREN statement
  |  FOR LPAREN declaration SEMICOLON SEMICOLON RPAREN statement
  ;


compound_statement:
     LCURL block_item_list RCURL
  |  LCURL RCURL
  ;

block_item_list:
     block_item
  |  block_item_list block_item
  ;

block_item:
     variable_declaration
  |  statement
  ;



line : line '\n'
     | '\n'
     |/*empty*/
     |error '\n' {yyerror("reenter previous line:");
     			yyerrok;}
     ;			
%%
int main(int argc, char *argv[])
{
	yyin = fopen(argv[1],"r");
	printf("package tests;\nimport mat.*;\n");
	printf("public class test{\n");
	yyparse();
	printf("}\n}\n");

	return 0;
}

int yerror(char *msg)
{
	printf("Errrrr~~\n", msg);
}
